﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
namespace WenSkin.Controls
{
    public class WenListBox : ListBox
    {
        public WenListBox()
        {
            base.SetStyle(
                //ControlStyles.UserPaint |
                ControlStyles.DoubleBuffer |
                ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.ResizeRedraw |
                ControlStyles.SupportsTransparentBackColor, true);
            base.UpdateStyles();
            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.IntegralHeight = false;
            ItemHeight = 23;
        }

        #region 委托事件

        [Category("Wen"), Description("项被点击事件")]
        public event WenListBoxEventHandler ItemClick;

        #endregion

        #region 私有属性

        //选中项改变之前的选中项索引
        private int selectBefore = -1;

        private int MouseItemIndex;
        private bool line = true;
        private bool radioBox = true;
        private Color oneRowColor = Color.DeepSkyBlue;
        private Color towRowColor = Color.Aquamarine;
        private Color selectedRowColor = Color.DarkCyan;
        private Color mouseMoveRowColor = Color.Cyan;
        private int itemHeight;

        #endregion

        #region 公有属性

        [Category("Wen"), Description("是否增加序号"), DefaultValue(true)]
        public bool Line { get => line; set { line = value; this.Invalidate(); } }

        [Category("Wen"), Description("是否增加选框"), DefaultValue(true)]
        public bool RadioBox { get => radioBox; set { radioBox = value; this.Invalidate(); } }

        [Category("Wen"), Description("奇数行颜色"), DefaultValue(typeof(Color), "DeepSkyBlue")]
        public Color OneRowColor { get => oneRowColor; set { oneRowColor = value; this.Invalidate(); } }

        [Category("Wen"), Description("偶数行颜色"), DefaultValue(typeof(Color), "Aquamarine")]
        public Color TowRowColor { get => towRowColor; set { towRowColor = value; this.Invalidate(); } }

        [Category("Wen"), Description("选中颜色"), DefaultValue(typeof(Color), "DarkCyan")]
        public Color SelectedRowColor { get => selectedRowColor; set { selectedRowColor = value; this.Invalidate(); } }

        [Category("Wen"), Description("鼠标移动行颜色"), DefaultValue(typeof(Color), "Cyan")]
        public Color MouseMoveRowColor { get => mouseMoveRowColor; set { mouseMoveRowColor = value; this.Invalidate(); } }

        #endregion

        #region 数据绑定
        [Category("WenData"), Description("绑定数据列"), DefaultValue(null)]
        public string ColumnName { get; set; }
        private object dataSource { get; set; }
        [Browsable(false)]
        public new object DataSource
        {
            get => dataSource;
            set
            {
                if (value != null)
                {
                    dataSource = value;
                    DataBind();
                }
            }
        }
        private void DataBind()
        {
            if (dataSource == null)
                return;
            this.Items.Clear();

            //分类数据绑定
            switch (dataSource)
            {
                case DataSet ds:
                    DataBindDataTable(ds.Tables[0]);
                    break;
                case DataTable dt:
                    DataBindDataTable(dt);
                    break;
                case IList ilist:
                    if (string.IsNullOrWhiteSpace(ColumnName))
                    {
                        foreach (var li in ilist)
                        {
                            List<System.Reflection.PropertyInfo> propertyInfos = new List<System.Reflection.PropertyInfo>(li.GetType().GetProperties());
                            string value = propertyInfos.Find(a => a.Name.ToUpper() == ColumnName.ToUpper())?.GetValue(li, null)?.ToString();
                            Items.Add(value);
                        }
                    }
                    else
                    {
                        foreach (var li in ilist)
                        {
                            string value = li.GetType().GetProperties()[0].GetValue(li, null)?.ToString();
                            Items.Add(value);
                        }
                    }
                    break;
                default:
                    break;
            }

            //绑定数据   
            void DataBindDataTable(DataTable dt)
            {
                if (string.IsNullOrWhiteSpace(ColumnName))
                    foreach (DataRow dr in dt.Rows)
                    {
                        Items.Add(dr[0]);
                    }
                else
                    foreach (DataRow dr in dt.Rows)
                    {
                        Items.Add(dr[ColumnName]);
                    }
            }
        }
        #endregion

        #region 重置属性或者重写属性

        [Category("Wen"), Description("设置单项高度"), DefaultValue(23)]
        public new int ItemHeight { get => itemHeight; set { base.ItemHeight = value; itemHeight = value; } }

        #endregion

        #region 执行重绘

        //重绘指定项
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            //base.OnDrawItem(e);
            if (Items.Count == 0 || e.Index < 0)
                return;
            Graphics g = e.Graphics;
            Rectangle rec = GetItemRectangle(e.Index);
            if (GetSelected(e.Index))
            {
                rec.Inflate(0, -2);
                ItemDraw(e.Index, g, rec, SelectedRowColor, e);
            }
            else if (e.Index == MouseItemIndex)
            {
                ItemDraw(e.Index, g, rec, MouseMoveRowColor, e);
            }
            else if (e.Index % 2 != 1)
            {
                ItemDraw(e.Index, g, rec, OneRowColor, e);
            }
            else
            {
                ItemDraw(e.Index, g, rec, TowRowColor, e);
            }
        }

        //刷新指定项目
        private void ItemDraw(int index, Graphics g, Rectangle rec, Color c, DrawItemEventArgs e)
        {
            ControlHelper.SetGDIHigh(g);

            using Brush backColor = new SolidBrush(c);
            g.FillRectangle(backColor, rec);

            using Brush brush = new SolidBrush(e.ForeColor);

            int radioWidth = 0;
            if (RadioBox)
            {
                radioWidth = 20;
                g.DrawEllipse(new Pen(brush) { Width = 2 }, new Rectangle(rec.X, (ItemHeight - 15) / 2 + rec.Y, 15, 15));
                if (GetSelected(index))
                    g.FillEllipse(brush, new Rectangle(rec.X + 5, (ItemHeight - 5) / 2 + rec.Y, 5, 5));
            }

            //绘制文字
            if (Line)
            {
                Rectangle recLine = new Rectangle(rec.X + radioWidth, rec.Y, 50 - radioWidth, this.ItemHeight);
                Rectangle recText = new Rectangle(rec.X + 50, rec.Y, rec.Width - 50, this.ItemHeight);
                g.DrawString((index + 1).ToString(), Font, brush, recLine, ControlHelper.StringConters);
                g.DrawString(Items[index]?.ToString(), Font, brush, recText, ControlHelper.StringConters);
            }
            else
            {
                Rectangle recText = new Rectangle(rec.X + radioWidth, rec.Y, rec.Width - radioWidth, this.ItemHeight);
                g.DrawString(Items[index]?.ToString(), Font, brush, recText, ControlHelper.StringConters);
            }

        }

        //鼠标移动
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            int index = IndexFromPoint(e.Location);
            if (index < 0)
                return;
            if (MouseItemIndex != index)
            {
                int indexBefore = MouseItemIndex;
                MouseItemIndex = index;

                this.RefreshItem(index);
                this.RefreshItem(indexBefore);
            }
        }

        //刷新指定索引项
        protected override void RefreshItem(int index)
        {
            if (index < 0 || Items.Count == 0)
                return;
            Graphics g = CreateGraphics();
            Rectangle rec = GetItemRectangle(index);
            g.SetClip(new Rectangle(rec.X, rec.Y + 1, rec.Width, rec.Height - 1));
            if (SelectedIndex == index)
                OnDrawItem(new DrawItemEventArgs(g, Font, rec, index, DrawItemState.Selected, Color.White, this.SelectedRowColor));
            else
                OnDrawItem(new DrawItemEventArgs(g, Font, rec, index, DrawItemState.None, this.ForeColor, this.SelectedRowColor));
        }

        //鼠标移开事件
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            int index = MouseItemIndex;
            MouseItemIndex = -1;
            RefreshItem(index);
        }
        //选中索引变化
        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
            if (selectBefore != -1)
            {
                RefreshItem(selectBefore);
            }
            selectBefore = SelectedIndex;
            object item = this.SelectedItem;
            ItemClick?.Invoke(this, new WenListBoxEventArgs(item));
        }
        #endregion
    }

    public delegate void WenListBoxEventHandler(object sender, WenListBoxEventArgs e);
    public class WenListBoxEventArgs : EventArgs
    {
        public WenListBoxEventArgs(object item)
        {
            this.Item = item;
        }
        public object Item { get; set; }
    }
}
